/*	--- 组合模式(Composite) --- 
(层级结构 必用)

#  将【对象】组合成【树形结构】以表示【“部分-整体”的层次结构】，使得【用户】对【单个对象】和【组合对象】的【使用】具有【一致性】。


=========================================================


【组合模式】（Composite） 经常用于【树形结构】。

为了简化代码，使用【Composite】可以把【一个叶子节点】与【一个父节点】统一起来【处理】。



我们来看一个具体的例子。

在 XML / HTML中，从【根节点】开始，【每个节点】都可能包含【任意个其他节点】，这些【层层嵌套的节点】就构成了【一颗树】。

要以【树的结构】表示 XML，我们可以先【抽象】出【节点类型Node】： */
public interface Node {
	// 添加【1个Node】为【子Node】
	Node add(Node node);

	// 获取【子Node】
	List<Node> children();

	// 输出为【XML】
	String toXml();
}


/*
对于一个【<abc>】这样的节点，我们称之为【ElementNode】，它可以作为【容器】包含【多个子节点】： */
public class ElementNode implements Node {

	private String name; // Node_name
	private List<Node> list = new ArrayList<>(); // children

	public ElementNode(String name) {
		this.name = name;
	}

	public Node add(Node node) {
		list.add(node); // List<Node>.add(Node)
		return this;
	}

	public String toXml() {
		String start = "<" + name + ">\n";
		String end = "</" + name + ">\n";
		StringJoiner sj = new StringJoiner("", start, end);
			// new StringJoiner(content, head, tail);

		list.forEach( node -> {
			sj.add(node.toXml() + "\n");
		}); // StringJoiner.add(x) 将x加入到StringJoiner的content中

		return sj.toString();
	}
}


/*
对于【普通文本】，我们把它看作【TextNode】，它没有【子节点】: */
public class TextNode implements Node {

	private String text;

	public TextNode(String text) {
		this.text = text;
	}

	public Node add(Node node) {
		throw new UnsupportedOperationException();	
			// 不支持操作Exception
	}

	public List<Node> children() {
		return List.of(); // 空List<Node>
	}

	public String toXml() {
		return text;
	}
}


/*
此外，还可以有【注释节点】： */
public class CommentNode implements Node {
	private String text;

	public CommentNode(String text) {
		this.text = text;
	}

	public Node add(Node node) {
		throw new UnsupportedOperationException();
	}

	public LIst<Node> children() {
		return List.of();
	}

	public String toXml() {
		return "<!-- " + text + " -->";
	}
}


/*
通过【ElementNode】、【TextNode】和【CommentNode】，我们就可以【构造】出一颗【树】： */
Node root = new ElementNode("school");

root.add(new ElementNode("classA")
	.add(new TextNode("Tom"))
	.add(new TextNode("Alice"))
);

root.add(new ElementNode("classB")
		.add(new TextNode("Bob"))
		.add(new TextNode("Grace"))
		.add(new CommentNode("comment..."))
);

System.out.println(root.toXml());



/*
最后通过【root节点】输出的【XML】如下： 

<school>
<classA>
Tom
Alice
</classA>
<classB>
Bob
Grace
<!-- comment... -->
</classB>
</school>





====================================================


#	练习


使用【Composite模式】构造XML */




/*======================================================


#	----- 组合Composite の 小结 -----


1. 【Composite模式】使得【叶子对象】和【容器对象】具有【一致性】，从而形成【统一的树形结构】，并用一致的方式去处理它们。


2. 使用Composite模式时，需要先统一单个节点以及“容器”节点的接口：

	             ┌───────────┐
	             │   Node    │
	             └───────────┘
	                   ▲
	      ┌────────────┼────────────┐
	      │            │            │
	┌───────────┐┌───────────┐┌───────────┐
	│ElementNode││ TextNode  ││CommentNode│
	└───────────┘└───────────┘└───────────┘

作为容器节点的ElementNode又可以添加任意个Node，这样就可以构成层级结构。

类似的，像【文件夹】和【文件】、【GUI窗口 的 各种组件】， 都符合【Composite模式】的定义，因为【它们的结构】天生就是【层级结构】。






*/










